home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / c / net / rcmd.c < prev    next >
C/C++ Source or Header  |  1990-05-04  |  7KB  |  316 lines

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that this notice is preserved and that due credit is given
  7.  * to the University of California at Berkeley. The name of the University
  8.  * may not be used to endorse or promote products derived from this
  9.  * software without specific prior written permission. This software
  10.  * is provided ``as is'' without express or implied warranty.
  11.  */
  12.  
  13. #if defined(LIBC_SCCS) && !defined(lint)
  14. static char sccsid[] = "@(#)rcmd.c    5.16 (Berkeley) 3/7/88";
  15. #endif /* LIBC_SCCS and not lint */
  16.  
  17. #include <stdio.h>
  18. #include <ctype.h>
  19. #include <pwd.h>
  20. #include <sys/param.h>
  21. #include <sys/file.h>
  22. #include <sys/signal.h>
  23. #include <sys/socket.h>
  24. #include <sys/stat.h>
  25.  
  26. #include <netinet/in.h>
  27.  
  28. #include <netdb.h>
  29. #include <errno.h>
  30. #include <strings.h>
  31.  
  32. extern    errno;
  33. extern char *inet_ntoa();
  34.  
  35. rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
  36.     char **ahost;
  37.     u_short rport;
  38.     char *locuser, *remuser, *cmd;
  39.     int *fd2p;
  40. {
  41.     int s, timo = 1, pid;
  42.     int oldmask;
  43.     struct sockaddr_in sin, from;
  44.     char c;
  45.     int lport = IPPORT_RESERVED - 1;
  46.     struct hostent *hp;
  47.  
  48.     pid = getpid();
  49.  
  50.     sin.sin_addr.s_addr = inet_addr(*ahost);
  51.     if (sin.sin_addr.s_addr != -1) {
  52.     sin.sin_family = AF_INET;
  53.     } else {
  54.     hp = gethostbyname(*ahost);
  55.     if (hp == 0) {
  56.         fprintf(stderr, "%s: unknown host\n", *ahost);
  57.         return (-1);
  58.     }
  59.     *ahost = hp->h_name;
  60.     sin.sin_family = hp->h_addrtype;
  61.     bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, hp->h_length);
  62.     }
  63.     oldmask = sigblock(sigmask(SIGURG));
  64.     for (;;) {
  65.         s = rresvport(&lport);
  66.         if (s < 0) {
  67.             if (errno == EAGAIN)
  68.                 fprintf(stderr, "socket: All ports in use\n");
  69.             else
  70.                 perror("rcmd: socket");
  71.             sigsetmask(oldmask);
  72.             return (-1);
  73.         }
  74.         fcntl(s, F_SETOWN, pid);
  75.         sin.sin_port = rport;
  76.         if (connect(s, (struct sockaddr *) &sin, sizeof (sin)) >= 0)
  77.             break;
  78.         (void) close(s);
  79.         if (errno == EADDRINUSE) {
  80.             lport--;
  81.             continue;
  82.         }
  83.         if (errno == ECONNREFUSED && timo <= 16) {
  84.             sleep(timo);
  85.             timo *= 2;
  86.             continue;
  87.         }
  88.         if (hp->h_addr_list[1] != NULL) {
  89.             int oerrno = errno;
  90.  
  91.             fprintf(stderr,
  92.                 "connect to address %s: ", inet_ntoa(sin.sin_addr));
  93.             errno = oerrno;
  94.             perror((char *) 0);
  95.             hp->h_addr_list++;
  96.             bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr,
  97.                 hp->h_length);
  98.             fprintf(stderr, "Trying %s...\n",
  99.                 inet_ntoa(sin.sin_addr));
  100.             continue;
  101.         }
  102.         perror(hp->h_name);
  103.         sigsetmask(oldmask);
  104.         return (-1);
  105.     }
  106.     lport--;
  107.     if (fd2p == 0) {
  108.         write(s, "", 1);
  109.         lport = 0;
  110.     } else {
  111.         char num[8];
  112.         int s2 = rresvport(&lport), s3;
  113.         int len = sizeof (from);
  114.  
  115.         if (s2 < 0)
  116.             goto bad;
  117.         listen(s2, 1);
  118.         (void) sprintf(num, "%d", lport);
  119.         if (write(s, num, strlen(num)+1) != strlen(num)+1) {
  120.             perror("write: setting up stderr");
  121.             (void) close(s2);
  122.             goto bad;
  123.         }
  124.         s3 = accept(s2, &from, &len);
  125.         (void) close(s2);
  126.         if (s3 < 0) {
  127.             perror("accept");
  128.             lport = 0;
  129.             goto bad;
  130.         }
  131.         *fd2p = s3;
  132.         from.sin_port = ntohs((u_short)from.sin_port);
  133.         if (from.sin_family != AF_INET ||
  134.             from.sin_port >= IPPORT_RESERVED) {
  135.             fprintf(stderr,
  136.                 "socket: protocol failure in circuit setup.\n");
  137.             goto bad2;
  138.         }
  139.     }
  140.     (void) write(s, locuser, strlen(locuser)+1);
  141.     (void) write(s, remuser, strlen(remuser)+1);
  142.     (void) write(s, cmd, strlen(cmd)+1);
  143.     if (read(s, &c, 1) != 1) {
  144.         perror(*ahost);
  145.         goto bad2;
  146.     }
  147.     if (c != 0) {
  148.         while (read(s, &c, 1) == 1) {
  149.             (void) write(2, &c, 1);
  150.             if (c == '\n')
  151.                 break;
  152.         }
  153.         goto bad2;
  154.     }
  155.     sigsetmask(oldmask);
  156.     return (s);
  157. bad2:
  158.     if (lport)
  159.         (void) close(*fd2p);
  160. bad:
  161.     (void) close(s);
  162.     sigsetmask(oldmask);
  163.     return (-1);
  164. }
  165.  
  166. rresvport(alport)
  167.     int *alport;
  168. {
  169.     struct sockaddr_in sin;
  170.     int s;
  171.  
  172.     sin.sin_family = AF_INET;
  173.     sin.sin_addr.s_addr = INADDR_ANY;
  174.     s = socket(AF_INET, SOCK_STREAM, 0);
  175.     if (s < 0)
  176.         return (-1);
  177.     for (;;) {
  178.         sin.sin_port = htons((u_short)*alport);
  179.         if (bind(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0)
  180.             return (s);
  181.         if (errno != EADDRINUSE) {
  182.             (void) close(s);
  183.             return (-1);
  184.         }
  185.         (*alport)--;
  186.         if (*alport == IPPORT_RESERVED/2) {
  187.             (void) close(s);
  188.             errno = EAGAIN;        /* close */
  189.             return (-1);
  190.         }
  191.     }
  192. }
  193.  
  194. ruserok(rhost, superuser, ruser, luser)
  195.     char *rhost;
  196.     int superuser;
  197.     char *ruser, *luser;
  198. {
  199.     FILE *hostf;
  200.     char fhost[MAXHOSTNAMELEN];
  201.     int first = 1;
  202.     register char *sp, *p;
  203.     int baselen = -1;
  204.  
  205.     sp = rhost;
  206.     p = fhost;
  207.     while (*sp) {
  208.         if (*sp == '.') {
  209.             if (baselen == -1)
  210.                 baselen = sp - rhost;
  211.             *p++ = *sp++;
  212.         } else {
  213.             *p++ = isupper(*sp) ? tolower(*sp++) : *sp++;
  214.         }
  215.     }
  216.     *p = '\0';
  217.     hostf = superuser ? (FILE *)0 : fopen("/etc/hosts.equiv", "r");
  218. again:
  219.     if (hostf) {
  220.         if (!_validuser(hostf, fhost, luser, ruser, baselen)) {
  221.             (void) fclose(hostf);
  222.             return(0);
  223.         }
  224.         (void) fclose(hostf);
  225.     }
  226.     if (first == 1) {
  227.         struct stat sbuf;
  228.         struct passwd *pwd;
  229.         char pbuf[MAXPATHLEN];
  230.  
  231.         first = 0;
  232.         if ((pwd = getpwnam(luser)) == NULL)
  233.             return(-1);
  234.         (void)strcpy(pbuf, pwd->pw_dir);
  235.         (void)strcat(pbuf, "/.rhosts");
  236.         if ((hostf = fopen(pbuf, "r")) == NULL)
  237.             return(-1);
  238.         (void)fstat(fileno(hostf), &sbuf);
  239.         if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) {
  240.             fclose(hostf);
  241.             return(-1);
  242.         }
  243.         goto again;
  244.     }
  245.     return (-1);
  246. }
  247.  
  248. _validuser(hostf, rhost, luser, ruser, baselen)
  249. char *rhost, *luser, *ruser;
  250. FILE *hostf;
  251. int baselen;
  252. {
  253.     char *user;
  254.     char ahost[MAXHOSTNAMELEN];
  255.     register char *p;
  256.  
  257.     while (fgets(ahost, sizeof (ahost), hostf)) {
  258.         p = ahost;
  259.         while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
  260.             *p = isupper(*p) ? tolower(*p) : *p;
  261.             p++;
  262.         }
  263.         if (*p == ' ' || *p == '\t') {
  264.             *p++ = '\0';
  265.             while (*p == ' ' || *p == '\t')
  266.                 p++;
  267.             user = p;
  268.             while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0')
  269.                 p++;
  270.         } else
  271.             user = p;
  272.         *p = '\0';
  273.         if (_checkhost(rhost, ahost, baselen) &&
  274.             !strcmp(ruser, *user ? user : luser)) {
  275.             return (0);
  276.         }
  277.     }
  278.     return (-1);
  279. }
  280.  
  281. _checkhost(rhost, lhost, len)
  282. char *rhost, *lhost;
  283. int len;
  284. {
  285.     static char ldomain[MAXHOSTNAMELEN + 1];
  286.     static char *domainp = NULL;
  287.     static int nodomain = 0;
  288.     register char *cp;
  289.  
  290.     if (len == -1)
  291.         return(!strcmp(rhost, lhost));
  292.     if (strncmp(rhost, lhost, len))
  293.         return(0);
  294.     if (!strcmp(rhost, lhost))
  295.         return(1);
  296.     if (*(lhost + len) != '\0')
  297.         return(0);
  298.     if (nodomain)
  299.         return(0);
  300.     if (!domainp) {
  301.         if (gethostname(ldomain, sizeof(ldomain)) == -1) {
  302.             nodomain = 1;
  303.             return(0);
  304.         }
  305.         ldomain[MAXHOSTNAMELEN] = NULL;
  306.         if ((domainp = index(ldomain, '.')) == (char *)NULL) {
  307.             nodomain = 1;
  308.             return(0);
  309.         }
  310.         for (cp = ++domainp; *cp; ++cp)
  311.             if (isupper(*cp))
  312.                 *cp = tolower(*cp);
  313.     }
  314.     return(!strcmp(domainp, rhost + len +1));
  315. }
  316.